一般而言,我們都會希望控管使用者在系統內的權限,而 Laravel 提供了非常便利的工具,無論是預設或是客製驗證流程都很方便。
目前專案透過 SSO(如 Keycloak)登入後會取得一組 JWT Token。
Laravel 認證流程改為使用 自訂的 guard 和 user provider 來支援這種驗證邏輯。
config/auth.php
設定:
'guards' => [
'api' => [
'driver' => 'sso', // 自訂 guard
'provider' => 'custom', // 對應的 user provider
],
],
'providers' => [
'custom' => [
'driver' => 'custom', // 自訂 user provider
],
],
app/Auth/CustomApiProvider.php
namespace App\Auth;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Auth\GenericUser;
class CustomApiProvider implements UserProvider
{
public function retrieveByCredentials(array $credentials)
{
// 模擬從 JWT token 解析出 user info
$user = [
'id' => 1,
'employeeNo' => 'A001',
'name' => 'Harry',
'jobName' => 'Engineer',
'access' => 'admin',
];
return $this->getGenericUser($user);
}
public function getGenericUser(array $user)
{
return new GenericUser($user);
}
// 其他方法為了相容性可簡單實作或留空
public function retrieveById($identifier) {}
public function retrieveByToken($identifier, $token) {}
public function updateRememberToken(Authenticatable $user, $token) {}
public function validateCredentials(Authenticatable $user, array $credentials) {
return true;
}
}
app/Providers/AppServiceProvider.php
use App\Auth\CustomApiProvider;
use Illuminate\Support\Facades\Auth;
use Illuminate\Contracts\Foundation\Application;
public function boot(): void
{
Auth::provider('custom', function (Application $app, array $config) {
return new CustomApiProvider();
});
}
php artisan make:middleware RoleCheck
app/Http/Middleware/RoleCheck.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class RoleCheck
{
public function handle(Request $request, Closure $next): Response
{
$user = Auth::user();
// 這裡以 admin 為例,視情況修改權限邏輯
if (!$user || $user->access !== 'admin') {
return response()->json(['message' => 'Forbidden'], 403);
}
return $next($request);
}
}
app/Http/Kernel.php
protected $routeMiddleware = [
// ...
'role.check' => \App\Http\Middleware\RoleCheck::class,
];
routes/api.php
use Illuminate\Support\Facades\Route;
Route::middleware(['auth:api', 'role.check'])->group(function () {
Route::get('/', function () {
return response()->json([
'status' => 'success',
'user' => Auth::user(),
]);
});
});
如此一來就可以透過客製的驗證方式來驗證使用者權限!